#include "spi_hard_drv.h"
#include <stdio.h>
/**
 * @desc  : Gpio配置
 * @date  : 2025-04-25
 * @author: AnRui
 * @note  :
 */
static void  GpioConfig(void) {
    // SCL 推挽输出
    rcu_periph_clock_enable(SPI_HARD_CLK_RCU);
    gpio_init(SPI_HARD_CLK_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, SPI_HARD_CLK_PIN);
    // MOSI 推挽输出
    rcu_periph_clock_enable(SPI_HARD_MOSI_RCU);
    gpio_init(SPI_HARD_MOSI_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, SPI_HARD_MOSI_PIN);
    // MISO	上拉输入
    rcu_periph_clock_enable(SPI_HARD_MISO_RCU);
    gpio_init(SPI_HARD_MISO_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, SPI_HARD_MISO_PIN);
}

/**
 * @desc  : SPI配置
 * @date  : 2025-04-25
 * @author: AnRui
 * @note  :
 */
static void SpiConfig() {
    rcu_periph_clock_enable(SPI_RCU_X);
    spi_parameter_struct spiInitStruct;
    spi_struct_para_init(&spiInitStruct);
    //全双工 接受和发送在同一个周期
    spiInitStruct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
    // 主机
    spiInitStruct.device_mode = SPI_MASTER;
    // 8bit
    spiInitStruct.frame_size = SPI_FRAMESIZE_8BIT;
    /// Mode 0 (CPOL=0, CPHA=0)
    spiInitStruct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
    // 软件控制片选
    spiInitStruct.nss = SPI_NSS_SOFT;
    // 二分频
    spiInitStruct.prescale = SPI_PSC_2;
    // 高位优先
    spiInitStruct.endian = SPI_ENDIAN_MSB;
    spi_init(USE_SPI_X, &spiInitStruct);
    spi_enable(USE_SPI_X);
}

/**
 * @desc  : SPI硬件初始化
 * @date  : 2025-04-25
 * @author: AnRui
 * @note  :
 */
void SpiHardDrvInit(void) {
    GpioConfig();
    SpiConfig();
}

/**
 * @desc  : SPI发送和接收数据
 * @date  : 2025-04-25
 * @author: AnRui
 * @param : data - {参数说明}:
 * @return: uint8_t
 * @note  :
 */
uint8_t SpiHardDrvReadWriteByte(uint8_t data) {
    /* loop while data register in not emplty */
    while (RESET == spi_i2s_flag_get(USE_SPI_X, SPI_FLAG_TBE));
    /* send byte through the SPI0 peripheral */
    spi_i2s_data_transmit(USE_SPI_X, data);
    uint32_t timeout = OUT_TIMES;
    /* wait to receive a byte */
    // 即使主机不需要接收数据，MISO线仍会在每个时钟周期返回1bit数据
    while (RESET == spi_i2s_flag_get(USE_SPI_X, SPI_FLAG_RBNE)) {
        timeout--;
        if (timeout == 0) { break; }
    }
    /* return the byte read from the SPI bus */
    return spi_i2s_data_receive(USE_SPI_X);
}
